<?php

/**
 * This is the model class for table "{{article}}".
 *
 * The followings are the available columns in table '{{article}}':
 * @property integer $id
 * @property integer $catid
 * @property string $title
 * @property string $alias
 * @property integer $status
 * @property integer $featured
 * @property integer $can_comment
 * @property string $language
 * @property string $meta_description
 * @property string $meta_keyword
 * @property string $robots
 * @property string $author
 * @property integer $checkout
 * @property string $create_date
 * @property string $created_by
 * @property string $update_date
 * @property string $updated_by
 * @property integer $hits
 * @property string $fulltext
 * @property string $introtext
 * The followings are the available model relations:
 * @property Category $cat
 */
class Article extends CActiveRecord {

    const SCENARIO_SEARCH = 'search';
    const SCENARIO_CREATE = 'create';
    const SCENARIO_UPDATE = 'update';
    const ALIAS_MAX_LENGTH = 50;

    /**
     * Returns the static model of the specified AR class.
     * @param string $className active record class name.
     * @return Article the static model class
     */
    public static function model($className = __CLASS__) {
	return parent::model($className);
    }

    /**
     * @return string the associated database table name
     */
    public function tableName() {
	return '{{article}}';
    }

    /**
     * @return array validation rules for model attributes.
     */
    public function rules() {
	// NOTE: you should only define rules for those attributes that
	// will receive user inputs.
	return array(
	    array('title, catid, status, fulltext, language, featured', 'required', 'message' => t('MSG_REQUIRED', 'messages')),
	    array('catid, status, featured, checkout, hits', 'numerical', 'integerOnly' => true),
	    array('title, meta_keyword, created_by, updated_by', 'length', 'max' => 255, 'tooLong' => t('MSG_STRING_TOO_LONG', 'messages')),
	    array('alias', 'length', 'max' => Article::ALIAS_MAX_LENGTH, 'tooLong' => t('MSG_STRING_TOO_LONG', 'messages')),
	    array('language', 'length', 'max' => 25, 'tooLong' => t('MSG_STRING_TOO_LONG', 'messages')),
	    array('meta_description', 'length', 'max' => 500, 'tooLong' => t('MSG_STRING_TOO_LONG', 'messages')),
	    //array('introtext', 'length', 'max' => 1000, 'tooLong' => t('MSG_STRING_TOO_LONG', 'messages')),
	    array('robots', 'length', 'max' => 30, 'tooLong' => t('MSG_STRING_TOO_LONG', 'messages')),
	    array('author', 'length', 'max' => 50, 'tooLong' => t('MSG_STRING_TOO_LONG', 'messages')),
	    array('create_date, update_date, introtext, fulltext', 'safe'),
	    //array('catid', 'checkExistOfCaterogy', 'on' => Article::SCENARIO_CREATE .','. Article::SCENARIO_UPDATE),
	    // The following rule is used by search().
	    // Please remove those attributes that should not be searched.
	    array('id, catid, title, alias, status, featured, language, meta_description, meta_keyword, robots, author, checkout, create_date, created_by, update_date, updated_by, hits, fulltext', 'safe', 'on' => Article::SCENARIO_SEARCH),
	);
    }

    /**
     * @return array relational rules.
     */
    public function relations() {
	// NOTE: you may need to adjust the relation name and the related
	// class name for the relations automatically generated below.
	return array(
	    'cat' => array(self::BELONGS_TO, 'Category', 'catid'),
	);
    }

    /**
     * @return array customized attribute labels (name=>label)
     */
    public function attributeLabels() {
	return array(
	    'id' => t('LBL_ID', 'article'),
	    'catid' => t('LBL_CATEGORY', 'article'),
	    'title' => t('LBL_TITLE', 'article'),
	    'alias' => t('LBL_ALIAS', 'article'),
	    'introtext' => t('LBL_INTRO_TEXT', 'article'),
	    'fulltext' => t('LBL_FULL_TEXT', 'article'),
	    'status' => t('LBL_STATUS', 'article'),
	    'featured' => t('LBL_FEATURED', 'article'),
	    'can_comment' => t('LBL_ALLOW_COMMENT', 'article'),
	    'language' => t('LBL_LANGUAGE', 'article'),
	    'meta_description' => t('LBL_META_DESCRIPTION', 'article'),
	    'meta_keyword' => t('LBL_META_KEYWORDS', 'article'),
	    'robots' => t('LBL_ROTBOTS', 'article'),
	    'author' => t('LBL_AUTHOR', 'article'),
	    'checkout' => t('LBL_CHECKOUT', 'article'),
	    'create_date' => t('LBL_CREATE_DATE', 'article'),
	    'created_by' => t('LBL_CREATED_BY', 'article'),
	    'update_date' => t('LBL_UPDATE_DATE', 'article'),
	    'updated_by' => t('LBL_UPDATED_BY', 'article'),
	    'hits' => t('LBL_HITS', 'article'),
	);
    }

    /**
     * Retrieves a list of models based on the current search/filter conditions.
     * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
     */
    public function search() {
	// Warning: Please modify the following code to remove attributes that
	// should not be searched.
	$a = $this->scenario;
	$criteria = new CDbCriteria;

	$criteria->compare('id', $this->id);
	$criteria->compare('catid', $this->catid);
	$criteria->addSearchCondition('title', trim($this->title));
	$criteria->compare('alias', $this->alias, true);
	$criteria->compare('fulltext', $this->fulltext, true);
	$criteria->compare('introtext', $this->introtext, true);

	//When user select all, show pushlished and unpublish items, not show trashed items
	if (!isset($this->status) || is_string($this->status) && strlen($this->status) == 0) {
	    $criteria->addCondition('status <> :status');
	    $criteria->params = array_merge($criteria->params, array(':status' => LGConstantArticleStatus::TRASHED));
	} else {
	    $criteria->compare('status', $this->status);
	}

	$criteria->compare('featured', $this->featured);
	$criteria->compare('can_comment', $this->can_comment);

	if ($this->language == "*") {
	    $this->language = "";
	}
	$criteria->compare('language', $this->language, true);

	$criteria->compare('meta_description', $this->meta_description, true);
	$criteria->compare('meta_keyword', $this->meta_keyword, true);
	$criteria->compare('robots', $this->robots, true);
	$criteria->compare('author', $this->author, true);
	$criteria->compare('checkout', $this->checkout);
	$criteria->compare('create_date', $this->create_date, true);
	$criteria->compare('created_by', $this->created_by, true);
	$criteria->compare('update_date', $this->update_date, true);
	$criteria->compare('updated_by', $this->updated_by, true);
	$criteria->compare('hits', $this->hits);

	$rows = new CActiveDataProvider($this, array(
	    'criteria' => $criteria,
	    'pagination' => array(
		'pageSize' => LGHelpers::getPageSize($this->count()),
	    ),
	    'sort' => array(
		'defaultOrder' => array(
		    'id' => CSort::SORT_DESC
		)
	    ),
	));

	//Chnage update date to show for user
	foreach ($rows->data as $row) {
	    $updateDateTimeSpan = strtotime($row->update_date);
	    $row->update_date = date(LGConstant::DATE_FORMAT, $updateDateTimeSpan);

	    if ($row->update_date == LGConstant::DATE_DEFAULT) {
		$row->update_date = '';
	    }
	}

	return $rows;
    }

    public function beforeSave() {
	if (parent::beforeSave()) {
	    $current_date = date(LGConstant::DATE_FORMAT_FOR_DATABASE);
	    $logedInUser = User::model()->findByPk(Yii::app()->user->id);

	    if ($this->isNewRecord) {
		$this->create_date = $current_date;
		$this->created_by = $logedInUser->username;
	    }

	    $this->update_date = $current_date;
	    $this->updated_by = $logedInUser->username;

	    $this->alias = !isset($this->alias) || $this->alias == "" ?
		    substr(stringSafe($this->title), 0, Article::ALIAS_MAX_LENGTH) : stringURLSafe($this->alias);

	    return true;
	}
	else
	    return false;
    }

    protected function afterFind() {
	parent::afterFind();

	if ($this->scenario == self::SCENARIO_SEARCH) {
	    $updateDateTimeSpan = strtotime($this->update_date);
	    $this->update_date = date(LGConstant::DATE_FORMAT, $updateDateTimeSpan);

	    if ($this->update_date == LGConstant::DATE_DEFAULT) {
		$this->update_date = '';
	    }
	}

	//Remove tag <script>, prevent XSS
	$this->introtext = strip_tags_content($this->introtext, '<script>', true);
	$this->fulltext = strip_tags_content($this->fulltext, '<script>', true);
    }

    //TODO :Comment will be affect to font-end
    public function findLatestNews($category_id, $count) {
	setLanguage(isset($_GET['lang']) ? $_GET['lang'] : null);

	if (isset($_GET['lang'])) {
	    $language = $_GET['lang'];
	} else {
	    $settingLanguage = Settings::model()->findAll();
	    $language = $settingLanguage[0]->language;
	}
	$criteria = new CDbCriteria();
	$criteria->addCondition("status = :status AND catid = :catid and (language = :language OR language = '*')");
	$criteria->params = array(':catid' => $category_id, ':language' => $language, ':status' => LGConstant::PUBLISH_STATUS);
	$criteria->order = 'id DESC';
	$criteria->limit = $count;
	$news = $this->findAll($criteria);

	return $news;
    }

    public function searchArticle($keyword, $lang) {
	$criteria = new CDbCriteria;
	$encodeKey = mb_convert_encoding(htmlspecialchars($keyword, ENT_QUOTES), 'HTML-ENTITIES', 'UTF-8');
	$criteria->condition = ("(introtext REGEXP :keyword OR `fulltext` REGEXP :keyword OR title LIKE :searchKey)
                                    AND (language = :lang OR language like '*')
                                    AND status = :status");
	$criteria->params = (array(':keyword' => '>[^<]*' . $encodeKey,
	    ':searchKey' => "%" . strtr($keyword, array('%' => '\%', '_' => '\_', '\\' => '\\\\')) . "%",
	    ':lang' => $lang,
	    ':status' => LGConstant::PUBLISH_STATUS,));
	return new CActiveDataProvider($this, array(
	    'criteria' => $criteria,
	    'pagination' => array(
		'pageSize' => LGConstant::FRONTEND_SEARCH_PAGE_SIZE,
	    ),
	));
    }

    public function getListByCategoryId($category_id, $language = null, $status = 1, $pageSize = 1) {
	$language = isset($language) ? $language : '*';

	$criteria = new CDbCriteria();
	$criteria->addCondition("catid = :category_id and status = :status and (language = :language or language = '*')");
	$criteria->params = array('category_id' => $category_id, 'status' => $status, 'language' => $language);
	$criteria->order = 'create_date DESC';

	return new CActiveDataProvider($this, array(
	    'criteria' => $criteria,
	    'pagination' => array(
		'pageSize' => $pageSize,
	    )
	));
    }

    /**
     * Search with keyword
     * @param type $keyword
     * @return \CActiveDataProvider if keyword is empty, result ActiveDataProvider with empty array.
     * Else return articles have published status and title constant keyword
     */
    public static function searchWithKeyword($keyword, $pageSize = 10) {

	$model = new Article(Article::SCENARIO_SEARCH);
	$model->scenario = Article::SCENARIO_SEARCH;

	$criteria = new CDbCriteria;

	if (empty($keyword)) {
	    $results = new CActiveDataProvider($model, array('data' => array()));
	} else {
	    $criteria->compare('status', LGConstant::PUBLISH_STATUS);
	    $criteria->compare('title', $keyword, true);
	    $criteria->order = 'title ASC';

	    if ($pageSize == null || $pageSize == 0) {
		$pageSize = 10;
	    }

	    $results = new CActiveDataProvider($model, array(
		'criteria' => $criteria,
		'pagination' => array(
		    'pageSize' => $pageSize,
		)
	    ));
	}

	/**
	 * @param Article $result
	 */
	foreach ($results->data as $result) {

	    $result->scenario = Article::SCENARIO_SEARCH;
	    $result->afterFind();

	    $fullText = $result->introtext . '</br>' . $result->fulltext;
	    if (!empty($fullText)) {
		$trimText = self::standardizeSearchResult($fullText);

		$len = mb_strlen($trimText, 'UTF-8');

		if ($len >= 200) {
		    $result->introtext = mb_substr($trimText, 0, 200, 'UTF-8');
		    $result->introtext .= '...';
		} else {
		    $result->introtext = $trimText;
		}
	    }
	}

	return $results;
    }

    private static function standardizeSearchResult($text) {
	//Convent ISO-8859-1 to UTF-8 to substring extractly
	$text = html_entity_decode($text, ENT_COMPAT, 'UTF-8');

	$stripsString = strip_tags($text);

	$trimText = str_replace(array("\r\n", "\r", "\n"), "\n", $stripsString);
	$trimText = str_replace(array(' '), " ", $trimText);
	$lines = explode("\n", $trimText);
	$new_lines = array();

	foreach ($lines as $i => $line) {
	    if (!empty($line)) {
		//Remove excess space character
		$trimedString = trim($line);
		$words = explode(' ', $trimedString);
		$newWords = array();
		
		foreach ($words as $word) {
		    $trimedWord = trim($word);

		    if ($trimedWord != null && strlen($trimedWord) > 0 && $trimedWord != " ") {
			$newWords[] = $trimedWord;
		    }
		}
		
		$standardString = implode(' ', $newWords);
		$new_lines[] = $standardString;
	    }
	}
	
	$trimText = implode("\n", $new_lines);

	return $trimText;
    }

    /**
     * 
     * @param string $keyword
     * @return int
     */
    public static function countSearchResultWithKeyword($keyword) {
	$model = Article::model();

	$criteria = new CDbCriteria;
	if (empty($keyword)) {
	    return 0;
	} else {
	    $criteria->compare('status', LGConstant::PUBLISH_STATUS);
	    $criteria->compare('title', $keyword, true);
	}
	return $model->count($criteria);
    }

}